package top.bingoz.wanandroid.di.module

import android.content.Context
import dagger.Module
import dagger.Provides
import okhttp3.Cache
import okhttp3.ConnectionPool
import okhttp3.OkHttpClient
import okhttp3.ResponseBody
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Converter
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import top.bingoz.wanandroid.common.Constants
import top.bingoz.wanandroid.data.http.ApiService
import top.bingoz.wanandroid.data.http.intercept.HttpLogger
import top.bingoz.wanandroid.data.http.intercept.NetInterceptor
import top.bingoz.wanandroid.loge
import java.io.File
import java.lang.reflect.Type
import java.util.concurrent.TimeUnit
import javax.inject.Singleton

/**
 * @author su
 * @date 2018/7/27
 * @description 使用Provides  类必须non-abstract 或者static methods
 */
@Module
class HttpModule {
    private class NullOnEmptyConverterFactory : Converter.Factory() {
        override fun responseBodyConverter(type: Type, annotations: Array<out Annotation>, retrofit: Retrofit?): Converter<ResponseBody, *>? {

            val converter: Converter<ResponseBody, Any> = retrofit!!.nextResponseBodyConverter<Any>(this, type, annotations)

            return Converter<ResponseBody, Any> { body: ResponseBody ->
                if (body.contentLength() == 0L) {
                    null
                } else {
                    converter.convert(body)
                }
            }
        }

    }

    //设置缓存目录和缓存空间大小
    @Provides
    @Singleton
    fun provideCache(context: Context): Cache? {
        var cache: Cache? = null
        try {
            cache = Cache(File(context.cacheDir, "http-cache"), 10 * 1024 * 1024)
        } catch (e: Exception) {
            loge(e)
        }
        return cache
    }


    @Provides
    @Singleton
    fun provideOkHttpClient(cache: Cache?): OkHttpClient {
        val logInterceptor = HttpLoggingInterceptor(HttpLogger())
        logInterceptor.level = HttpLoggingInterceptor.Level.BODY
        return OkHttpClient.Builder()
                .addInterceptor(logInterceptor)
                .addNetworkInterceptor(NetInterceptor())
                .cache(cache)
                .readTimeout(10, TimeUnit.SECONDS)
                .writeTimeout(10, TimeUnit.SECONDS)
                .connectionPool(ConnectionPool(8, 10, TimeUnit.SECONDS))
                .build()

    }

    @Provides
    @Singleton
    fun provideRetrofit(baseUrl: String, okHttpClient: OkHttpClient): Retrofit {
        return Retrofit.Builder()
                //设置服务器路径
                .baseUrl(baseUrl)
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .addConverterFactory(NullOnEmptyConverterFactory())
                .addConverterFactory(GsonConverterFactory.create())
                //设置使用okhttp网络请求
                .client(okHttpClient)
                .build()
    }


    @Provides
    @Singleton
    fun provideUrl(): String {
        return Constants.URL.SERVER
    }


    @Provides
    @Singleton
    fun provideApiService(retrofit: Retrofit): ApiService {
        return retrofit.create(ApiService::class.java)
    }


    companion object {

        private var apiService: ApiService? = null


        fun apiService(context: Context): ApiService {
            if (apiService == null) {
                val module = HttpModule()


                val url = module.provideUrl()
                val cache = module.provideCache(context)
                val client = module.provideOkHttpClient(cache)
                val retrofit = module.provideRetrofit(url, client)
                apiService = module.provideApiService(retrofit)
            }
            return apiService!!
        }

    }

}
